package cn.fz.utils;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Hex;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 海上船舶接口sign签名工具类
 */
@Slf4j
public class SignatureGeneratorUtils {
    private static String sortAndConcatParams(Map<String, Object> params) {
        List<String> keys = new ArrayList<>(params.keySet());
        Collections.sort(keys);

        StringBuilder sortedParams = new StringBuilder();
        for (String key : keys) {
            sortedParams.append(params.get(key));
        }
        return sortedParams.toString();
    }

    private static String encodeToHex(String paramStr) {
        byte[] bytes = paramStr.getBytes(StandardCharsets.UTF_8);
        char[] hexChars = Hex.encodeHex(bytes);
        return new String(hexChars);
    }

    private static String getSHA256(String data) throws NoSuchAlgorithmException {
        MessageDigest digest = MessageDigest.getInstance("SHA-256");
        byte[] hash = digest.digest(data.getBytes(StandardCharsets.UTF_8));
        return bytesToHex(hash);
    }

    private static String bytesToHex(byte[] hash) {
        StringBuilder hexString = new StringBuilder(2 * hash.length);
        for (byte b : hash) {
            String hex = Integer.toHexString(0xff & b);
            if (hex.length() == 1) {
                hexString.append('0');
            }
            hexString.append(hex);
        }
        return hexString.toString();
    }

    public static String generatorSign(Map<String, Object> params) throws UnsupportedEncodingException, NoSuchAlgorithmException {
        // 步骤1: 准备数据并排序拼接
        String str = sortAndConcatParams(params);
        log.info("步骤1字符串: {}", str);

        // 步骤2: 对步骤1字符串进行UTF-8编码后计算HEX值
        String encodedStr = URLEncoder.encode(str, StandardCharsets.UTF_8);
        String hexEncodedStr = encodeToHex(encodedStr);
        log.info("步骤2字符串: {}", hexEncodedStr);

        // 步骤3: 计算步骤2字符串的SHA-256哈希值
        String signStr = getSHA256(hexEncodedStr);
        log.info("步骤3签名: {}", signStr);

        return signStr;
    }
}
